/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.increment;

import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.controlrule.rule.BeControlRule;
import com.inspur.edp.bef.bizentity.controlrule.rule.convert.BeControlRuleConvertor;
import com.inspur.edp.bef.bizentity.controlrule.ruledefinition.entity.BeControlRuleDef;
import com.inspur.edp.bef.bizentity.increment.BizEntityIncrement;
import com.inspur.edp.bef.bizentity.increment.extract.BizEntityExtractor;
import com.inspur.edp.bef.bizentity.increment.merger.BizEntityMerger;
import com.inspur.edp.cef.designtime.api.element.increment.GspCommonFieldIncrement;
import com.inspur.edp.cef.designtime.api.element.increment.ModifyFieldIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.CommonEntityIncrement;
import com.inspur.edp.cef.designtime.api.entity.increment.ModifyEntityIncrement;
import com.inspur.edp.cef.designtime.api.increment.IncrementType;
import com.inspur.edp.cef.designtime.api.increment.property.PropertyIncrement;
import com.inspur.edp.das.commonmodel.entity.increment.CommonModelIncrement;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.metadata.rtcustomization.api.AbstractCustomizedContent;
import com.inspur.edp.metadata.rtcustomization.spi.CustomizationExtHandler;
import com.inspur.edp.metadata.rtcustomization.spi.args.*;
import java.util.HashMap;
import java.util.Map;

public class BizEntityExtHandler implements CustomizationExtHandler {

  @Override
  public AbstractCustomizedContent getExtContent4SameLevel(Compare4SameLevelArgs args) {
    GspMetadata oldMetadata = args.getOldMetadata();
    GspMetadata newMetadata = args.getMetadata();
    if (oldMetadata == null) {
      throw new RuntimeException("增量抽取时，更新前的元数据为空");
    }
    if (newMetadata == null) {
      throw new RuntimeException("增量抽取时，更新后的元数据为空");
    }

    BizEntityExtractor extractor = new BizEntityExtractor(!oldMetadata.isExtended());
    GspBusinessEntity oldBe = (GspBusinessEntity) oldMetadata.getContent();
    GspBusinessEntity newBe = (GspBusinessEntity) newMetadata.getContent();

    BeControlRuleDef def = new BeControlRuleDef();
    BeControlRule rule = new BeControlRule();
    BeControlRuleConvertor.convert2ControlRule(def, rule, oldBe);
    return extractor.extract(oldBe, newBe, rule, def);
  }

  //region changeMerge
  @Override
  public AbstractCustomizedContent changeMerge(ChangeMergeArgs changeMergeArgs) {
    CommonModelIncrement parentChange = (CommonModelIncrement) changeMergeArgs.getParentChage();
    CommonModelIncrement extendChange = (CommonModelIncrement) changeMergeArgs.getChangeToParent();

    if (parentChange == null) {
      return null;
    }
    if (extendChange == null) {
      return parentChange;
    }
    mergeChangeProperties(parentChange.getChangeProperties(), extendChange.getChangeProperties());

    if (extendChange.getMainEntityIncrement() != null
        && parentChange.getMainEntityIncrement() != null) {
      mergeObjectIncrement(parentChange.getMainEntityIncrement(),
          extendChange.getMainEntityIncrement());
    }

    return parentChange;
  }


  private void mergeObjectIncrement(ModifyEntityIncrement parentIncrement,
      ModifyEntityIncrement extendIncrement) {

    mergeChangeProperties(parentIncrement.getChangeProperties(),
        extendIncrement.getChangeProperties());

    for (Map.Entry<String, CommonEntityIncrement> childPair : parentIncrement.getChildEntitis()
        .entrySet()) {
      if (childPair.getValue().getIncrementType() != IncrementType.Modify) {
        continue;
      }
      if (extendIncrement.getChildEntitis().containsKey(childPair.getKey())) {
        mergeObjectIncrement((ModifyEntityIncrement) childPair.getValue(),
            (ModifyEntityIncrement) extendIncrement.getChildEntitis().get(childPair.getKey()));
      }
    }

    for (Map.Entry<String, GspCommonFieldIncrement> elePair : parentIncrement.getFields()
        .entrySet()) {
      GspCommonFieldIncrement fieldIncrement = elePair.getValue();
      if (fieldIncrement.getIncrementType() != IncrementType.Modify) {
        continue;
      }
      HashMap<String, GspCommonFieldIncrement> extendFields = extendIncrement.getFields();
      if (extendFields.containsKey(elePair.getKey())) {
        mergeElementIncrement((ModifyFieldIncrement) fieldIncrement,
            (ModifyFieldIncrement) extendFields.get(elePair.getKey()));
      }
    }

  }

  private void mergeElementIncrement(ModifyFieldIncrement parentIncrement,
      ModifyFieldIncrement extendIncrement) {
    mergeChangeProperties(parentIncrement.getChangeProperties(),
        extendIncrement.getChangeProperties());
  }

  private void mergeChangeProperties(HashMap<String, PropertyIncrement> parentChanges,
      HashMap<String, PropertyIncrement> extendChanges) {
    for (Map.Entry<String, PropertyIncrement> changePair : extendChanges.entrySet()) {
      parentChanges.remove(changePair.getKey());
    }
  }

  //endregion

  @Override
  public AbstractCustomizedContent getExtContent(
      ExtContentArgs args) {//GspMetadata oldMetadata, GspMetadata newMetadata) {
    GspMetadata oldMetadata = args.getBasicMetadata();
    GspMetadata newMetadata = args.getExtMetadata();
    if (oldMetadata == null) {
      throw new RuntimeException("增量抽取时，更新前的元数据为空");
    }
    if (newMetadata == null) {
      throw new RuntimeException("增量抽取时，更新后的元数据为空");
    }
    BizEntityExtractor extractor = new BizEntityExtractor();
    GspBusinessEntity oldBe = (GspBusinessEntity) oldMetadata.getContent();
    GspBusinessEntity newBe = (GspBusinessEntity) newMetadata.getContent();

    BeControlRuleDef def = new BeControlRuleDef();
    BeControlRule rule = new BeControlRule();
    BeControlRuleConvertor.convert2ControlRule(def, rule, oldBe);
    return extractor.extract(oldBe, newBe, rule, def);
  }


  @Override
  public GspMetadata merge(
      MetadataMergeArgs args) {//GspMetadata extendMetadata, AbstractCustomizedContent baseIncrement) {

    GspMetadata extendMetadata = args.getExtendMetadata();
    AbstractCustomizedContent baseIncrement = args.getCustomizedContent();
    GspMetadata metadata = (GspMetadata) extendMetadata.clone();
    if (metadata == null) {
      throw new RuntimeException("增量合并时，扩展元数据为空");
    }
    BizEntityMerger merger = new BizEntityMerger(true);
//        GspBusinessEntity extendBe = (GspBusinessEntity)metadata.getContent();
    GspBusinessEntity extendBe = ((GspBusinessEntity) extendMetadata.getContent()).clone();

//        CustomizationService service = SpringBeanUtils.getBean(CustomizationService.class);
//        CommonModelIncrement extendIncrement = (CommonModelIncrement)service.getChangeset(metadata.getHeader().getId() ,null, null);
//        GspBusinessEntity mergedBe = (GspBusinessEntity)merger.merge(extendBe, extendIncrement == null ? new CommonModelIncrement():extendIncrement, (CommonModelIncrement)baseIncrement, new MonkControlRule());
//        metadata.setContent(mergedBe);

    BeControlRuleDef def = new BeControlRuleDef();
    BeControlRule rule = new BeControlRule();
    GspMetadata baseBeMetadata = args.getRootMetadata();
    BeControlRuleConvertor
        .convert2ControlRule(def, rule, (GspBusinessEntity) baseBeMetadata.getContent());
    BizEntityIncrement extendIncrement = (BizEntityIncrement) args.getCustomizedContent();
    GspBusinessEntity mergedBe = (GspBusinessEntity) merger
        .merge(extendBe, (GspBusinessEntity) args.getRootMetadata().getContent(),
            extendIncrement == null ? new BizEntityIncrement() : extendIncrement,
            (BizEntityIncrement) baseIncrement, rule, def);
    metadata.setContent(mergedBe);

    return metadata;
  }

}
